package edu.hawaii.webspider;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;

/**
 * Implements a URL cataloging system.
 * 
 * @author Andrew Wong
 *
 */
public class WebAddressDatabase {

  Map<String, WebAddressEntry> database;
  List<String> urlQueue;
  
  /**
   * Initializes the data structures used to hold the URL links.
   */
  WebAddressDatabase() {
    database = new TreeMap<String, WebAddressEntry>();
    urlQueue = new ArrayList<String>();
  }
  
  /**
   * Adds a URL to the database.  Also increments the count of number of times
   * the URL shows up by one.  If the URL is not in the database, it is added.
   * 
   * @param url URL to be added.
   */
  void addUrl(String url) {
    WebAddressEntry result = database.get(url);
    
    if (result == null) {  // a new url
      result = new WebAddressEntry();
      urlQueue.add(url);
    }
    
    result.count++;
    
    database.put(url, result);
  }
  
  /**
   * Marks a URL in the database as being 'visited'.
   * 
   * @param url URL to mark off.
   */
  void markUrl(String url) {
    WebAddressEntry result = database.get(url);
    
    if (result == null) {  // a new url
      result = new WebAddressEntry();
    }
    
    result.visited = true;
    
    database.put(url, result);
  }
  
  /**
   * Retrieves the number of times the URL has been added to the database.
   * 
   * @param url URL in question.
   * @return 'count' property corresponding to the URL.
   */
  int getCount(String url) {
    WebAddressEntry result = database.get(url);
    
    if (result == null) {  // a new url
      return 0;
    }
    
    return result.count;
  }
  
  /**
   * Checks if a URL has been marked as visited.
   * 
   * @param url URL in question.
   * @return Returns true if the URL has been marked off at least once, false otherwise.
   */
  public boolean visited(String url) {
    WebAddressEntry result = database.get(url);
    if (result == null) {        // must check if URL is in database
      return false;
    }
    return result.visited;
  }
  
  /**
   * Gets the next URL that has not been visited yet.
   * 
   * @return Next unvisited URL, or null if all URLs in database have been visited.
   */
  public String getNextUnvisited() {
    if (urlQueue.isEmpty()) {
      return null;
    }

    String result;
    do {
    result = urlQueue.get(0);
    urlQueue.remove(0);
    } while (this.visited(result) );
    return result;
  }
  
  /**
   * Retrieves the number of distinct URLs in the database.
   * 
   * @return Number of distinct URLs that have been added to the database.
   */
  public int getUrlCount() {
    return database.size();
  }

  /**
   * Retrieves the most popular link in the database.  If there is a tie, it returns
   * the first match via iteration of the corresponding key set.
   * 
   * @return URL key value with highest 'count' attribute.
   */
  public String getMostPopular() {
    Set<String> urlList = database.keySet();
    String bestUrl = "";
    int bestCount = 0;
    
    for (String element : urlList) {
      if (this.getCount(element) > bestCount) {
        bestUrl = element;
        bestCount = this.getCount(element);
      }
    }
    
    return bestUrl;
  }

}
